<?php

namespace Biz\service\BrandRights;

use Biz\cache\brand\Brand as cBrand;
use Biz\model\brand\Brand as mBrand;
use Biz\model\brandAccount\BrandAccountAuth;
use Biz\model\brandAccount\BrandAccountInfo;
use Biz\model\brandRights\BrandLevelRights as mBrandLevelRights;
use Biz\model\brandRights\BrandLevelRightsConfig as mBrandLevelRightsConfig;
use Biz\model\brandRights\BrandLevelRightsLeaveInfo as mBrandLevelRightsLeaveInfo;
use Biz\model\brandRights\BrandLevelRightsLog as mBrandLevelRightsLog;
use Biz\model\brandRights\BrandLevelRightsSource as mBrandLevelRightsSource;
use Biz\model\brandRights\BrandPackageRights as mBrandPackageRights;
use Biz\model\brandRights\BrandRightsAll as mBrandRightsAll;
use Biz\model\brandRights\BrandRightsRecored as mBrandRightsRecored;
use Biz\model\brandRights\BrandRightsSource as mBrandRightsSource;
use Biz\pockets\constInterface\BrandLevel;
use Biz\pockets\constInterface\SourceRightsInterface;
use Biz\pockets\serviceTrait\_Async;
use Doraemon\pockets\constInterface\LinkConf;
use Doraemon\pockets\constInterface\PopupServiceConf;
use Doraemon\pockets\datebase\BaseDbModel;
use Doraemon\service\DingTalkAlert;
use Doraemon\tools\Hhzurl;
use Doraemon\tools\ImgUrl;
use Doraemon\tools\LinkFormat;
use Doraemon\tools\Log;
use Doraemon\model\Phone as PhoneModel;
use hhz\constant\basic\UserExtendPhoneScene;
use Doraemon\service\Member\PhoneCrypto;

class BrandLevelRightsService implements BrandLevel
{
    use _Async;

    const LEVEL_RIGHTS_UNLOCK = 1; //解锁
    const LEVEL_RIGHTS_LOCK = 0; //未解锁

    const LEAVE_INFO_ERROR_COUNT_LIMIT = 1000; //留资上限
    const LEAVE_INFO_ERROR_RIGHTS_DISABLE = 1001; //权益不可用

    /**
     * 获取品牌等级权益
     * @param $brandId
     * @return array
     */
    public static function brandLevelRights($brandId)
    {
        $rights = [];
        $aResult = mBrandLevelRights::getBrandLevelRights($brandId, mBrandLevelRights::STATUS_NORMAL);
        if ($aResult && is_array($aResult)) {
            $rights = $aResult;
        }
        return $rights;
    }

    /**
     * 获取品牌用户已获取权益的情况
     * @param $uid
     * @param $iconType
     * @return array
     */
    public static function getBrandLevelRightsStateByUid($uid, $iconType)
    {
        $returnData = [];
        $brandInfo = mBrand::getBrandInfoByUid($uid);
        $brandId = $brandInfo['id'];

        $brandAccount = BrandAccountInfo::getOneByWhere([
            'type' => BrandAccountInfo::ACCOUNT_TYPE_BRAND,
            'brand_id' => $brandInfo['id'],
            'account_status' => BrandAccountInfo::ACCOUNT_STATUS_USED
        ], ['id', 'in_start_time', 'in_end_time']);

        if (empty($brandAccount)) {
            return $returnData;
        }

        $brandLevel = $brandInfo['level'];

        //获取全部权益
        $allRights = BrandLevelSourceRightsService::getLevelSourceRights();
        $allRightsIds = array_column($allRights, 'source_rights_id');

        $specRights = BrandRightsSourceService::getIdsByRightsNames([
            mBrandRightsSource::NEW_PRODUCT_GOODS_TEST_A,
            mBrandRightsSource::GOODS_TEST_B,
            mBrandRightsSource::GOODS_TEST_C,
        ]);
        $newProductGoodsTestAId = $specRights[mBrandRightsSource::NEW_PRODUCT_GOODS_TEST_A];
        $goodsTestBId = $specRights[mBrandRightsSource::GOODS_TEST_B];
        $goodsTestCId = $specRights[mBrandRightsSource::GOODS_TEST_C];

        //获取消耗型权益数量
        $sourceRightsIds = array_merge($allRightsIds, array_values($specRights));

        $brandRights = mBrandRightsAll::selectList([
            'brand_id' => $brandId,
            'rights_source_id' => $sourceRightsIds,
            'rights_status' => mBrandRightsAll::STATUS_NORMAL
        ], ['rights_source_id', 'rights_num']);
        $brandRightsNums = empty($brandRights) ? [] : array_column($brandRights, 'rights_num', 'rights_source_id');
        //权益获取最低等级
        $rightsMinLevels = BrandLevelRightsConfigService::getRightsMinLevel();
        //获取等级已获取的全部权益
        $brandOwnRights = self::brandLevelRights($brandId);
        $unlockCount = 0;
        $oMap = [];
        foreach ($brandOwnRights as $oRights) {
            if ($brandLevel >= $rightsMinLevels[$oRights['rights_source_id']]) {
                $unlockCount++;
            }
            $oMap[$oRights['rights_source_id']] = $oRights;
        }

        $rightsLevelConditions = BrandLevelRightsConfigService::getRightsLevels($brandId, $allRightsIds, $brandLevel,
            $rightsMinLevels);
        $todayCanUseRights = self::todayCanUse($brandId, self::LEAVE_INFO_CONSUME_LEAVEL_RIGHTS, $brandLevel,
            $rightsMinLevels);
        $leave_info_phone = self::getLeaveInfoPhone($brandId, $brandAccount['id']) ?? '';
        foreach ($allRights as $key => $rights) {
            //去除权益：社群推广、认领数增加、定制推广
            if (in_array($rights['rights_name'], ['community_promotion', 'content_receive', 'custom_promotion'])) {
                continue;
            }
            $minLevel = $rightsMinLevels[$rights['source_rights_id']];
            $rights_use_pic = !empty($rights['rights_use_pic']) ? ImgUrl::getUrl(ImgUrl::APPTYPE_BIZ,
                $rights['rights_use_pic'],
                ImgUrl::IMAGE_SIZE_ORI_NPHONE) : '';
            $returnData[$key]['source_rights_id'] = $rights['source_rights_id'];
            $returnData[$key]['rights_type'] = $rights['rights_type'];
            $returnData[$key]['rights_title'] = $rights['rights_title'];
            $returnData[$key]['rights_name'] = $rights['rights_name'];
            $returnData[$key]['link'] = self::getLinkUrl($rights['rights_name']);
            $returnData[$key]['rights_desc'] = $rights['rights_desc'];
            $returnData[$key]['sort_weight'] = $rights['sort_weight'];
            $returnData[$key]['rights_use_pic'] = $rights_use_pic;
            $returnData[$key]['state'] = $brandLevel >= $minLevel && isset($oMap[$rights['source_rights_id']]) ? strval(self::LEVEL_RIGHTS_UNLOCK) : strval(self::LEVEL_RIGHTS_LOCK);
            $rightsNum = isset($brandRightsNums[$rights['source_rights_id']]) ? $brandRightsNums[$rights['source_rights_id']] : 0;
            if ($rights['rights_name'] == mBrandRightsSource::NEW_PRODUCT || $rights['rights_name'] == mBrandRightsSource::GOODS_TEST_A) {
                $rightsNum = isset($brandRightsNums[$newProductGoodsTestAId]) ? $rightsNum + $brandRightsNums[$newProductGoodsTestAId] : $rightsNum;
                $rightsNum = $rights['rights_name'] == mBrandRightsSource::GOODS_TEST_A && isset($brandRightsNums[$goodsTestBId]) ? $rightsNum + $brandRightsNums[$goodsTestBId] : $rightsNum;
                $rightsNum = $rights['rights_name'] == mBrandRightsSource::GOODS_TEST_A && isset($brandRightsNums[$goodsTestCId]) ? $rightsNum + $brandRightsNums[$goodsTestCId] : $rightsNum;
            }
            $returnData[$key]['rights_num'] = intval($rightsNum);
            $rightsIcons = SourceRightsInterface::ALL_LEVEL_RIGHTS_ICONS[$iconType][$rights['rights_name']];
            $returnData[$key]['icon'] = $rightsIcons;
            $returnData[$key]['condition'] = $rightsLevelConditions[$rights['source_rights_id']] ?? [];
            $returnData[$key]['use_scene'] = self::SHOW_USE_BTN_LEVEL_RIGHTS[$rights['rights_name']] ?? [
                'platform' => [],
                'link' => '',
                'scene' => self::SCENE_NONE
            ];
            if (in_array($rights['rights_name'], self::LEAVE_INFO_CONSUME_LEAVEL_RIGHTS)) {
                $returnData[$key]['leave_info_phone'] = $leave_info_phone;
                $returnData[$key]['use_scene']['btn_enable'] = isset($todayCanUseRights[$rights['source_rights_id']]) ? $todayCanUseRights[$rights['source_rights_id']]['enable'] : 0;
                $returnData[$key]['use_scene']['toast_text'] = $returnData[$key]['use_scene']['btn_enable'] ? '' : ($brandLevel >= $minLevel ? '每天只允许申请一次哦，请耐心等待专属运营与你联系。' : '');
            }
        }
        $states = array_column($returnData, 'state');
        $sortWeight = array_column($returnData, 'sort_weight');
        array_multisort($states, SORT_DESC, $sortWeight, SORT_ASC, $returnData);
        return [$brandInfo, $unlockCount, $returnData];
    }

    /**
     * 生成跳转链接
     * @param $rights_name
     * @return mixed
     */
    private static function getLinkUrl($rights_name)
    {
        $link = sprintf("%s/brand/rights-and-interests/class-equity?key=%s", Hhzurl::getDomain(), $rights_name);
        $linkUrl = LinkFormat::encryptionLink($link);
        return $linkUrl;
    }

    /**
     * 获取更多链接
     * @return mixed
     */
    public static function getMoreLink()
    {
        $link = sprintf("%s/brand/rights-and-interests/growth-system", Hhzurl::getDomain());
        $linkArr = LinkFormat::generateLink(LinkConf::LINK_APP_FULLSCREEN, json_encode(['url' => $link]));
        $linkUrl = $linkArr['app_template'];
        return $linkUrl;
    }

    /**
     * 留资消耗权益
     * @param int $uid
     * @param string $rightsName
     * @param string $phone
     * @return bool
     */
    public static function leaveInfo($uid, $rightsName, $phone)
    {
        try {
            if (!in_array($rightsName, self::LEAVE_INFO_CONSUME_LEAVEL_RIGHTS)) {
                throw new \Exception('权益不可用于留资消费：' . $rightsName);
            }
            $brandInfo = mBrand::getBrandInfoByUid($uid);
            if (empty($brandInfo)) {
                throw new \Exception('品牌账户不存在：' . $uid);
            }
            $brandId = $brandInfo['id'];
            $brandName = $brandInfo['brand_name'];
            $level = $brandInfo['level'];
            $sourceRights = BrandLevelSourceRightsService::getRightsByRightsName($rightsName);
            if (!$sourceRights) {
                throw new \Exception('权益不存在：' . $rightsName);
            }
            $rightsId = $sourceRights['source_rights_id'];
            $rightsTitle = $sourceRights['rights_title'];
            $leaveInfoDate = date('Y-m-d', time());
            $where['brand_id'] = $brandId;
            $where['uid'] = $uid;
            $where['source_rights_id'] = $rightsId;
            $where['day'] = $leaveInfoDate;
            $hasLeaveInfo = mBrandLevelRightsLeaveInfo::dataHas($where);
            if ($hasLeaveInfo) {
                throw new \Exception('每天只允许申请一次哦，请耐心等待专属运营与你联系。', self::LEAVE_INFO_ERROR_COUNT_LIMIT);
            }
            $bRet = BrandEquityVerificationService::checkOneSourceStatus($brandId, $rightsName, true);
            if (!$bRet) {
                throw new \Exception('权益不可用', self::LEAVE_INFO_ERROR_RIGHTS_DISABLE);
            }
            $leaveInfoTime = date('Y-m-d H:i:s', time());
            $leaveInfo = [
                'brand_id' => $brandId,
                'uid' => $uid,
                'level' => $level,
                'source_rights_id' => $rightsId,
                'day' => $leaveInfoDate,
                'phone' => $phone,
                'addtime' => $leaveInfoTime,
                'edittime' => $leaveInfoTime,
            ];
            $bRet = mBrandLevelRightsLeaveInfo::dataInsert($leaveInfo);
            if (!$bRet) {
                throw new \Exception('留资失败！');
            }

            $rightsType = BrandRightsSourceService::getRightsTypeById($rightsId);
            if (!$rightsType) {
                throw new \Exception('权益类型错误！');
            }

            if ($rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM) {
                $dataParams = [
                    $brandId,
                    $rightsName,
                    mBrandRightsRecored::RECORED_TYPE_CONSUME,
                    mBrandRightsRecored::OPERATE_USER_TYPE_SYS,
                    $rightsId,
                ];
                $bRet = BrandEquityVerificationService::addOrSubBrandSourceNum(...$dataParams);
                if (!$bRet) {
                    throw new \Exception('消耗权益失败');
                }
            }
            $lvTitle = BrandLevel::BRAND_LEVELS[$level];
            $beerus_domain = str_replace('m.', 'beerus.', Hhzurl::getDomain());
            $jump_url = sprintf("%s/admin/BrandLevel/leave?&brand_id=%d&uid=%d&phone=%s&source_rights_id=%d&day=%s",
                $beerus_domain, $brandId, $uid, $phone, $rightsId, $leaveInfoDate);
            $alertMessage = [
                'title' => "品牌等级权益留资消费提醒",
                'brandId' => $brandId,
                'brandName' => $brandName,
                'lvTitle' => $lvTitle,
                'uid' => $uid,
                'rightsTitle' => $rightsTitle,
                'rightsName' => $rightsName,
                'phone' => $phone,
                'leaveInfoTime' => $leaveInfoTime,
                'jump_url' => $jump_url,
            ];
            self::dingAlert($alertMessage);

            return true;

        } catch (\Exception $e) {
            Log::error('leave-info:' . $e->getMessage(), func_get_args());
            if (self::LEAVE_INFO_ERROR_COUNT_LIMIT == $e->getCode()) {
                throw new \Exception($e->getMessage());
            }
            return false;
        }
    }

    /**
     * 升级弹窗扩展
     * @param $brandId
     * @param $level
     * @return array|string
     */
    public static function getLevelAlertExtend($brandId, $level)
    {
        $cackeKey = 'level_upgrade_alert_' . $brandId;
        $item = cBrand::getItem($cackeKey);
        if ($item) {
            if (!$item['has_alert'] && $item['level'] == $level) {
                $info = [
                    'level' => $item['level'],
                    'last_level' => $level,
                    'has_alert' => 1,
                ];
                cBrand::setItem($cackeKey, $info);
                return [
                    'type' => PopupServiceConf::STYLE_FLOATING,
                    "content" => [
                        "link" => self::getMoreLink(),
                        "img_url" => self::UPGRADE_REMINDER[$item['level']]
                    ]
                ];
            }
        }
        return '';
    }


    /**
     * 等级升级弹窗设置
     * @param $brandId
     * @param $level
     * @return bool
     */
    public static function setLevelUpgradeAlert($brandId, $level)
    {
        $cackeKey = 'level_upgrade_alert_' . $brandId;

        $alertInfo = [
            'level' => $level,
            'last_level' => $level - 1,
            'has_alert' => 0,
        ];
        cBrand::setItem($cackeKey, $alertInfo);
        return true;
    }


    /**
     * 判断权益今天是否可用
     * @param int $brandId
     * @param array $rightsNames
     * @param int $brandLevel
     * @param array $rightsMinLevels
     * @return array
     */
    public static function todayCanUse($brandId, $rightsNames, $brandLevel, $rightsMinLevels)
    {
        $sourceRightsList = BrandRightsSourceService::getAllSource('*',
            ['rights_name' => $rightsNames, 'data_status' => mBrandRightsSource::STATUS_NORMAL]);
        $rightsIds = array_column($sourceRightsList, 'id');
        $where['brand_id'] = $brandId;
        $where['source_rights_id'] = $rightsIds;
        $where['day'] = date('Y-m-d', time());
        $where['data_status'] = mBrandLevelRightsLeaveInfo::STATUS_NORMAL;
        $list = mBrandLevelRightsLeaveInfo::dataSelect($where);
        $listMap = array_column($list, null, 'source_rights_id');
        $returnData = [];
        foreach ($rightsIds as $rightsId) {
            $returnData[$rightsId]['enable'] = isset($listMap[$rightsId]) ? 0 : ($brandLevel >= $rightsMinLevels[$rightsId] ? 1 : 0);
        }
        return $returnData;
    }


    /**
     *
     * @param int $brandId
     * @return mixed|string
     */
    public static function getLeaveInfoPhone($brandId, $brandAccountId)
    {
        $where['brand_id'] = $brandId;
        $where['data_status'] = mBrandLevelRightsLeaveInfo::STATUS_NORMAL;
        $where['ORDER'] = ['id' => 'DESC'];
        $leaveInfo = mBrandLevelRightsLeaveInfo::dataSelectInfo($where);
        if ($leaveInfo && is_array($leaveInfo) && !empty($leaveInfo)) {
            $phone = $leaveInfo['phone_encrypt_id'] ? PhoneModel::getExtendPhone($leaveInfo['phone_encrypt_id'], UserExtendPhoneScene::BRAND_RIGHTS_LEAVE_INFO_PHONE) : '';
            return $phone;
        }
        $authInfo = BrandAccountAuth::getOneByWhere([
            'account_id' => $brandAccountId,
            'auth_status' => BrandAccountAuth::AUTH_STATUS_USED
        ]);
        $phone = $authInfo['phone_encrypt_id'] ? PhoneModel::getExtendPhone($authInfo['phone_encrypt_id'], UserExtendPhoneScene::BRAND_AUTH_INFO_PHONE) : '';
        return $phone;
    }

    /**
     * @param $uid
     * @return bool
     */
    public static function canTimePublish($uid)
    {
        $brandInfo = mBrand::getBrandInfoByUid($uid);
        if ($brandInfo) {
            $bRet = BrandEquityVerificationService::checkOneSourceStatus($brandInfo['id'],
                mBrandRightsSource::BRAND_TIME_TO_PUBLISH, true);
            return $bRet;
        }
        return false;
    }

    /**
     * 异步发送钉钉提醒
     * @param $message
     * @return void
     */
    public static function dingAlert($message)
    {
        self::_async($message);
    }

    public static function _async_dingAlert($message)
    {
        $msg = <<<MSG
## {$message['title']}
- 品牌ID: **{$message['brandId']}**
- 品牌名称: **{$message['brandName']}**
- 品牌等级: **{$message['lvTitle']}**
- 用户UID: **{$message['uid']}** 
- 权益名称: **{$message['rightsTitle']}**
- 权益标识: **{$message['rightsName']}**
- 手机号: **{$message['phone']}**
- 留资时间: **{$message['leaveInfoTime']}**
### 请及时关注、处理，并前往[运营后台]({$message['jump_url']})记录
MSG;
        DingTalkAlert::sendMarkdownMsg(DingTalkAlert::LEVEL_RIGHTS_CONSUME, $message['title'], $msg, true);
    }


    /**
     * 套餐续费时等级权益恢复
     * @param $brandId
     * @param int $startTime
     * @param int $endTime
     * @return bool
     */
    public static function levelRightsRecovery($brandId, $startTime, $endTime)
    {

        try {

            $brandInfo = mBrand::getBrandInfoById($brandId);

            $levelRightsCfg = BrandLevelRightsConfigService::getLevelRightsConfig($brandInfo['level'],
                mBrandLevelRightsConfig::STATUS_NORMAL);

            $brandLevelRights = BrandLevelRightsService::brandLevelRights($brandId);

            $brandRightsAll = BrandRightsAllService::getBrandRightsAllMap($brandId);

            $levelRightsSourceIds = mBrandLevelRightsSource::dataPluck(['data_status' => mBrandLevelRightsSource::STATUS_NORMAL],
                'source_rights_id');

            $rightsSourceMap = BrandRightsSourceService::getRightsSourceMap(['id' => $levelRightsSourceIds]);

            $insertData = [];

            $updateData = [];

            $resetData = [];

            $recordData = [];

            $setRightsData = [];

            foreach ($levelRightsCfg as $item) {
                $rightsType = $rightsSourceMap[$item['rights_source_id']]['rights_type'];
                //续费后数量型权益即使配置改动也不添加
                if ($rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM) {
                    continue;
                }
                $setRightsData[] = [
                    'brand_id' => $brandId,
                    'rights_source_id' => $item['rights_source_id'],
                    'reserve_rights_num' => $item['rights_data'],
                    'rights_num' => 0,
                ];
            }

            foreach ($brandLevelRights as $item) {
                $rightsType = $rightsSourceMap[$item['rights_source_id']]['rights_type'];
                //原来的等级消耗型权益数量恢复
                if ($rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM) {
                    if ($item['reserve_expire_time'] > time()) {
                        $setRightsData[] = $item;
                    } else {
                        $item['reserve_rights_num'] = 0;
                        $setRightsData[] = $item;
                    }
                }
                $resetData[] = [
                    [
                        'reserve_rights_num' => 0,
                        'reserve_expire_time' => 0,
                        'edittime' => date('Y-m-d H:i:s', time()),
                    ],
                    [
                        'id' => $item['id']
                    ]
                ];
            }

            foreach ($setRightsData as $item) {
                $index = $item['brand_id'] . '_' . $item['rights_source_id'];
                $rightsName = $rightsSourceMap[$item['rights_source_id']]['rights_name'];
                $totalNum = $rightsNum = $item['reserve_rights_num'];
                if (isset($brandRightsAll[$index])) {
                    $rights = $brandRightsAll[$index];
                    if ($rights['rights_status'] == mBrandRightsAll::STATUS_ON && $rights['end_time'] > time()) {
                        if ($item['reserve_rights_num'] == mBrandRightsSource::COUNT_UNLIMIT ||
                            $rights['rights_num'] == mBrandRightsSource::COUNT_UNLIMIT ||
                            $rights['total_num'] == mBrandRightsSource::COUNT_UNLIMIT) {
                            $rightsNum = $totalNum = mBrandRightsSource::COUNT_UNLIMIT;
                        } else {
                            $rightsNum = $item['reserve_rights_num'] + $rights['rights_num'];
                            $totalNum = $item['reserve_rights_num'] + $rights['total_num'];
                        }
                    }
                    $updateData[] = [
                        [
                            'brand_id' => $brandId,
                            'rights_source_id' => $item['rights_source_id'],
                            'rights_name' => $rightsName,
                            'rights_num' => $rightsNum,
                            'total_num' => $totalNum,
                            'start_time' => $startTime,
                            'end_time' => $endTime,
                            'rights_status' => mBrandRightsAll::STATUS_ON,
                            'addtime' => date('Y-m-d H:i:s', time()),
                            'edittime' => date('Y-m-d H:i:s', time()),
                        ],
                        [
                            'id' => $rights['id'],
                        ]
                    ];

                    $recordData[] = [
                        'brand_id' => $brandId,
                        'rights_name' => $rightsName,
                        'rights_source_id' => $item['rights_source_id'],
                        'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL_RECOVERY,
                        'source_id' => $brandInfo['level'],
                        'source_data' => json_encode([
                            'total_num' => $rights['total_num'],
                            'rights_num' => $rights['rights_num'],
                            'start_time' => $rights['start_time'],
                            'end_time' => $rights['end_time'],
                            'rights_status' => $rights['rights_status'],
                            'lv_rights_num' => $item['rights_num'],
                            're_lv_rights_num' => $item['reserve_rights_num'],
                        ]),
                        'operate_data' => json_encode([
                            'total_num' => $totalNum,
                            'rights_num' => $rightsNum,
                            'start_time' => $startTime,
                            'end_time' => $endTime,
                            'rights_status' => mBrandRightsAll::STATUS_ON
                        ]),
                    ];

                } else {
                    $insertData[] = [
                        'brand_id' => $brandId,
                        'rights_source_id' => $item['rights_source_id'],
                        'rights_name' => $rightsName,
                        'rights_num' => $rightsNum,
                        'total_num' => $totalNum,
                        'start_time' => $startTime,
                        'end_time' => $endTime,
                        'rights_status' => mBrandRightsAll::STATUS_ON,
                        'addtime' => date('Y-m-d H:i:s', time()),
                        'edittime' => date('Y-m-d H:i:s', time()),
                    ];

                    $recordData[] = [
                        'brand_id' => $brandId,
                        'rights_name' => $rightsName,
                        'rights_source_id' => $item['rights_source_id'],
                        'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL_RECOVERY,
                        'source_id' => $brandInfo['level'],
                        'source_data' => json_encode([
                            'lv_rights_num' => $item['rights_num'],
                            're_lv_rights_num' => $item['reserve_rights_num'],
                        ]),
                        'operate_data' => json_encode([
                            'total_num' => $totalNum,
                            'rights_num' => $rightsNum,
                            'start_time' => $startTime,
                            'end_time' => $endTime,
                            'rights_status' => mBrandRightsAll::STATUS_ON
                        ]),
                    ];
                }
            }

            $bResult = mBrandRightsAll::action(function () use ($insertData, $updateData, $recordData, $resetData) {
                if (!empty($insertData)) {
                    $result = mBrandRightsAll::insert($insertData);
                    if (!$result) {
                        return false;
                    }
                }
                if (!empty($updateData)) {
                    foreach ($updateData as $item) {
                        [$data, $where] = $item;
                        $result = mBrandRightsAll::updateData($data, $where);
                        if (!$result) {
                            return false;
                        }
                    }
                }
                if (!empty($recordData)) {
                    $result = mBrandRightsRecored::insert($recordData);
                    if (!$result) {
                        return false;
                    }
                }
                if (!empty($resetData)) {
                    $result = mBrandLevelRights::dataMultiUpdate($resetData);
                    if (!$result) {
                        return false;
                    }
                }
                return true;
            });

            if (!$bResult) {
                Log::error('恢复等级权益事务执行失败',
                    [
                        'mBrandRightsAll' => mBrandRightsAll::log(),
                        'mBrandRightsRecored' => mBrandRightsRecored::log(),
                        'mBrandLevelRights' => mBrandLevelRights::log(),
                    ]
                );
                throw new \Exception('事务执行失败');
            }

            return true;

        } catch (\Exception $e) {
            Log::error('续费恢复等级权益失败', ['params' => func_get_args(), 'error' => $e->getMessage()]);
            return false;
        }

    }

    /**
     * 等级权益更新（等级权益配置修改后去更新当前等级权益）
     * @param $brand
     * @param $level
     * @param $sourceRightsId
     * @param $rightsType
     * @param $rightsNum
     * @param $rightsStatus
     * @return array (string result, string msg)
     */
    public static function brandLevelRightsUpdate(
        $brand,
        $level,
        $sourceRightsId,
        $rightsType,
        $rightsNum,
        $rightsStatus
    )
    {
        $rightsNum = $rightsStatus != BaseDbModel::STATUS_NORMAL && $rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM ? 0 : $rightsNum;

        if (mBrandRightsSource::RIGHTS_TYPE_NUM == $rightsType) {
            if ($rightsNum >= mBrandRightsSource::COUNT_UNLIMIT) {
                $rightsNum = mBrandRightsSource::COUNT_UNLIMIT;
            }
        }

        //品牌账户信息
        $accountInfo = BrandAccountInfo::getOneByWhere([
            'type' => BrandAccountInfo::ACCOUNT_TYPE_BRAND,
            'brand_id' => $brand['id'],
            'account_status' => BrandAccountInfo::ACCOUNT_STATUS_USED
        ], ['id', 'in_start_time', 'in_end_time']);

        $startTime = strtotime($accountInfo['in_start_time']);
        $endTime = strtotime($accountInfo['in_end_time']);
        $endTime = strtotime(date('Y-m-d 23:59:59', $endTime));

        if (empty($accountInfo)) {
            return ['error', '不存在或则过期的品牌账户'];
        }
        if ($brand['level'] != $level) {//只更新当前等级的权益
            return ['error', '当前品牌等级和要更新的等级不一致'];
        }

        //处理等级权益日志
        $logWhere['brand_id'] = $brand['id'];
        $logWhere['level'] = $level;
        $logWhere['rights_source_id'] = $sourceRightsId;
        $brandLevelRightsLogInfo = mBrandLevelRightsLog::dataSelectInfo($logWhere);
        $oldLevelRightsNum = $brandLevelRightsLogInfo['rights_num'] ?? 0;

        $levelwhere['brand_id'] = $brand['id'];
        $levelwhere['rights_source_id'] = $sourceRightsId;
        $brandLevelRightsInfo = mBrandLevelRights::dataSelectInfo($levelwhere);

        $logInsertData = $logUpdateData = [];
        if (!empty($brandLevelRightsLogInfo)) {
            if ($rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM) {
                //已经存在的消耗型权益，则不更新
                return ['error', '当前等级已经存在该消费型权益'];
            }
            $data = [
                'rights_status' => $rightsStatus,
                'edittime' => date('Y-m-d H:i:s', time()),
                'rights_num' => $rightsNum,
            ];
            $logUpdateData = [
                $data,
                [
                    'id' => $brandLevelRightsLogInfo['id'],
                ]
            ];

        } elseif ($rightsStatus == BaseDbModel::STATUS_NORMAL) {
            $logInsertData = [
                'brand_id' => $brand['id'],
                'uid' => $brand['uid'],
                'level' => $level,
                'rights_source_id' => $sourceRightsId,
                'rights_num' => $rightsNum,
                'rights_status' => $rightsStatus,
                'addtime' => date('Y-m-d H:i:s', time()),
                'edittime' => date('Y-m-d H:i:s', time()),
            ];
        }

        $levelRightsInsertData = $levelRightsUpdateData = [];
        if (!empty($brandLevelRightsInfo)) {
            $data = [
                'rights_status' => $rightsStatus,
                'edittime' => date('Y-m-d H:i:s', time()),
            ];
            if (mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM == $rightsType) {
                $data['rights_num'] = $brandLevelRightsInfo['rights_num'] + $rightsNum;
            } elseif (mBrandRightsSource::RIGHTS_TYPE_NUM == $rightsType) {
                $data['rights_num'] = $rightsNum;
            } else {
                $data['rights_num'] = $rightsNum;
            }
            $levelRightsUpdateData = [
                $data,
                [
                    'brand_id' => $brand['id'],
                    'rights_source_id' => $sourceRightsId,
                ]
            ];
        } elseif ($rightsStatus == BaseDbModel::STATUS_NORMAL) {
            $levelRightsInsertData = [
                'brand_id' => $brand['id'],
                'uid' => $brand['uid'],
                'rights_source_id' => $sourceRightsId,
                'rights_num' => $rightsNum,
                'rights_status' => $rightsStatus,
                'addtime' => date('Y-m-d H:i:s', time()),
                'edittime' => date('Y-m-d H:i:s', time()),
            ];
        }
        //品牌权益总表
        $sourceRightsName = BrandRightsSourceService::getNameById($sourceRightsId);
        $allWhere['brand_id'] = $brand['id'];
        $allWhere['rights_source_id'] = $sourceRightsId;
        $allRightsInfo = mBrandRightsAll::getInfo($allWhere);

        $allRightsStatus = $rightsStatus;

        if (BaseDbModel::STATUS_DELETE == $allRightsStatus) {
            //套餐权益
            $packageRightsInfo = mBrandPackageRights::getInfo([
                'brand_id' => $brand['id'],
                'rights_source_id' => $sourceRightsId,
                'rights_status' => mBrandPackageRights::STATUS_NORMAL,
                'start_time[>=]' => $startTime,
                'end_time[<=]' => $endTime,
            ]);
            $allRightsStatus = !empty($packageRightsInfo) ? BaseDbModel::STATUS_NORMAL : $allRightsStatus;
        }

        if (BaseDbModel::STATUS_DELETE == $allRightsStatus) {
            //运营添加的权益
            $rightsRecoredInfo = mBrandRightsRecored::getInfo([
                'brand_id' => $brand['id'],
                'addtime[>=]' => $startTime,
                'addtime[<=]' => $endTime,
                'rights_source_id' => $sourceRightsId,
                'recored_type' => mBrandRightsRecored::RECORED_TYPE_ADMIN,
            ]);
            $allRightsStatus = !empty($rightsRecoredInfo) ? BaseDbModel::STATUS_NORMAL : $allRightsStatus;
        }

        if (mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM == $rightsType) {
            $newRightsNum = ($allRightsInfo['rights_num'] ?? 0) + $rightsNum;
            $totalNum = ($allRightsInfo['total_num'] ?? 0) + $rightsNum;
        } elseif (mBrandRightsSource::RIGHTS_TYPE_NUM == $rightsType) {
            if ($rightsNum >= mBrandRightsSource::COUNT_UNLIMIT) {
                $newRightsNum = mBrandRightsSource::COUNT_UNLIMIT;
                $totalNum = mBrandRightsSource::COUNT_UNLIMIT;
            } else {
                $newRightsNum = ($allRightsInfo['rights_num'] ?? 0) + $rightsNum - $oldLevelRightsNum;
                $totalNum = ($allRightsInfo['total_num'] ?? 0) + $rightsNum - $oldLevelRightsNum;
            }
        } else {
            $newRightsNum = $allRightsInfo['rights_num'] ?? 0;
            $totalNum = $allRightsInfo['total_num'] ?? 0;
        }

        $allRightsInsertData = $allRightsUpdateData = $rightsRecordData = [];

        if (!empty($allRightsInfo)) {
            $allRightsUpdateData = [
                [
                    'total_num' => $totalNum,
                    'rights_num' => $newRightsNum,
                    'start_time' => $startTime,
                    'end_time' => $endTime,
                    'rights_status' => $allRightsStatus,
                ],
                [
                    'id' => $allRightsInfo['id'],
                ]
            ];
            $rightsRecordData = [
                'brand_id' => $brand['id'],
                'rights_name' => $sourceRightsName,
                'rights_source_id' => $sourceRightsId,
                'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL,
                'source_id' => $level,
                'source_data' => json_encode([
                    'total_num' => $allRightsInfo['total_num'],
                    'rights_num' => $allRightsInfo['rights_num'],
                    'start_time' => $allRightsInfo['start_time'],
                    'end_time' => $allRightsInfo['end_time'],
                    'rights_status' => $allRightsInfo['rights_status'],
                ]),
                'operate_data' => json_encode([
                    'total_num' => $totalNum,
                    'rights_num' => $newRightsNum,
                    'start_time' => $startTime,
                    'end_time' => $endTime,
                    'rights_status' => $allRightsStatus
                ]),
            ];
        } elseif ($rightsStatus == BaseDbModel::STATUS_NORMAL) {
            $allRightsInsertData = [
                'brand_id' => $brand['id'],
                'rights_source_id' => $sourceRightsId,
                'rights_name' => $sourceRightsName,
                'total_num' => $rightsNum,
                'rights_num' => $rightsNum,
                'start_time' => $startTime,
                'end_time' => $endTime,
                'rights_status' => $allRightsStatus,
            ];
            $rightsRecordData[] = [
                'brand_id' => $brand['id'],
                'rights_name' => $sourceRightsName,
                'rights_source_id' => $sourceRightsId,
                'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL,
                'source_id' => $level,
                'source_data' => json_encode([]),
                'operate_data' => json_encode([
                    'total_num' => $rightsNum,
                    'rights_num' => $rightsNum,
                    'start_time' => $startTime,
                    'end_time' => $endTime,
                    'rights_status' => $allRightsStatus
                ]),
            ];
        }

        $result = mBrandLevelRightsLog::action(function () use (
            $logInsertData,
            $logUpdateData,
            $levelRightsInsertData,
            $levelRightsUpdateData,
            $allRightsInsertData,
            $allRightsUpdateData,
            $rightsRecordData
        ) {
            if (!empty($logInsertData)) {
                $bResult = mBrandLevelRightsLog::dataInsert($logInsertData);
                if (!$bResult) {
                    return false;
                }
            }
            if (!empty($logUpdateData)) {
                [$data, $where] = $logUpdateData;
                $bResult = mBrandLevelRightsLog::dataUpdate($data, $where);
                if (!$bResult) {
                    return false;
                }
            }
            if (!empty($levelRightsInsertData)) {
                $bResult = mBrandLevelRights::dataInsert($levelRightsInsertData);
                if (!$bResult) {
                    return false;
                }
            }
            if (!empty($levelRightsUpdateData)) {
                [$data, $where] = $levelRightsUpdateData;
                $bResult = mBrandLevelRights::dataUpdate($data, $where);
                if (!$bResult) {
                    return false;
                }
            }
            if (!empty($allRightsInsertData)) {
                $bResult = mBrandRightsAll::insert($allRightsInsertData);
                if (!$bResult) {
                    return false;
                }
            }
            if (!empty($allRightsUpdateData)) {

                [$data, $where] = $allRightsUpdateData;
                $bResult = mBrandRightsAll::update($data, $where);
                if (!$bResult) {
                    return false;
                }
            }
            if (!empty($rightsRecordData)) {
                $bResult = mBrandRightsRecored::insert($rightsRecordData);
                if (!$bResult) {
                    return false;
                }
            }
            return true;

        });

        if (!$result) {
            return ['error', '操作数据库失败'];
        }

        return ['success', 'successful'];
    }


    /**
     * 等级升级处理
     * @param $brandId
     * @param $level
     * @return bool
     */
    public static function afterLevelUp($brandId, $level, $lastLevel)
    {
        try {
            if (!isset(self::BRAND_LEVELS[$level]) || !isset(self::BRAND_LEVELS[$lastLevel]) || $level - $lastLevel != 1) {
                throw new \Exception('等级参数错误!');
            }

            //品牌账户信息
            $accountInfo = BrandAccountInfo::getOneByWhere([
                'type' => BrandAccountInfo::ACCOUNT_TYPE_BRAND,
                'brand_id' => $brandId,
                'account_status' => BrandAccountInfo::ACCOUNT_STATUS_USED
            ], ['id', 'uid', 'in_start_time', 'in_end_time']);
            if (empty($accountInfo)) {
                return false;
            }

            $startTime = strtotime($accountInfo['in_start_time']);
            $endTime = strtotime($accountInfo['in_end_time']);
            $endTime = strtotime(date('Y-m-d 23:59:59', $endTime));

            $levelSourceRights = BrandLevelSourceRightsService::getLevelSourceRights();
            $levelRightsIds = array_column($levelSourceRights, 'source_rights_id');
            $levelSourceRightsMap = BrandRightsSourceService::getRightsSourceMap(['id' => $levelRightsIds]);

            #获取品牌现有权益
            $brandRightsAll = mBrandRightsAll::selectList([
                'brand_id' => $brandId,
                'rights_source_id' => $levelRightsIds
            ]);
            $brandRightsAllMap = array_column($brandRightsAll, null, 'rights_source_id');
            //获取等级权益日志
            $logs = mBrandLevelRightsLog::dataSelect(['brand_id' => $brandId, 'level' => $level]);

            $isFirstUpgrade = empty($logs) ? true : false;

            $logsMap = array_column($logs, null, 'rights_source_id');

            $lastLevelRightsLogs = mBrandLevelRightsLog::dataSelect(['brand_id' => $brandId, 'level' => $lastLevel]);
            $lastLevelRightsLogsMap = array_column($lastLevelRightsLogs, null, 'rights_source_id');

            //查询等级配置文件，获取等级权益配置信息
            $levelRightsCfg = BrandLevelRightsConfigService::getLevelRightsConfig($level,
                mBrandLevelRightsConfig::STATUS_NORMAL);

            $levelRights = mBrandLevelRights::getBrandLevelRights($brandId);
            $levelRightsMap = array_column($levelRights, null, 'rights_source_id');

            //写等级权益日志,删除不在配置文件中的非消耗型权益
            $levelRightsLogInsert = $levelRightsLogUpdate = [];
            $levelRightsInsert = $levelRightsUpdate = [];
            $rightsAllInsert = $rightsAllUpdate = [];
            $recordInsert = [];
            foreach ($levelRightsCfg as $cfg) {
                $rightsType = $levelSourceRightsMap[$cfg['rights_source_id']]['rights_type'];
                //当该等级的消耗型权益已获得，不再获得同等级的其他新增的消耗型权益
                if (!$isFirstUpgrade && mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM == $rightsType) {
                    continue;
                }
                $lastRightsNum = isset($lastLevelRightsLogsMap[$cfg['rights_source_id']]) ? $lastLevelRightsLogsMap[$cfg['rights_source_id']]['rights_num'] : 0;
                //等级权益日志
                if (isset($logsMap[$cfg['rights_source_id']])) {
                    $log = $logsMap[$cfg['rights_source_id']];
                    $levelRightsLogUpdate[] = [
                        [
                            'rights_num' => $cfg['rights_data'],
                            'rights_status' => mBrandLevelRightsLog::STATUS_NORMAL,
                            'addtime' => date('Y-m-d H:i:s', time()),
                            'edittime' => date('Y-m-d H:i:s', time()),
                        ],
                        [
                            'id' => $log['id']
                        ]
                    ];
                } else {
                    $levelRightsLogInsert[] = [
                        'brand_id' => $brandId,
                        'uid' => $accountInfo['uid'],
                        'level' => $level,
                        'rights_source_id' => $cfg['rights_source_id'],
                        'rights_num' => $cfg['rights_data'],
                        'rights_status' => mBrandLevelRightsLog::STATUS_NORMAL,
                        'addtime' => date('Y-m-d H:i:s', time()),
                        'edittime' => date('Y-m-d H:i:s', time()),
                    ];
                }
                //等级权益
                if (isset($levelRightsMap[$cfg['rights_source_id']])) {
                    $lRights = $levelRightsMap[$cfg['rights_source_id']];
                    if ($lRights['rights_status'] != mBrandLevelRights::STATUS_NORMAL) {
                        $lRights['rights_num'] = $lastRightsNum = 0;
                    }
                    if (mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM == $rightsType) {
                        $rights_num = $lRights['rights_num'] + $cfg['rights_data'];
                    } elseif (mBrandRightsSource::RIGHTS_TYPE_NUM) {
                        $rights_num = $cfg['rights_data'];
                    } else {
                        $rights_num = $lRights['rights_num'];
                    }
                    $levelRightsUpdate[] = [
                        [
                            'rights_num' => $rights_num,
                            'rights_status' => mBrandLevelRights::STATUS_NORMAL,
                            'edittime' => date('Y-m-d H:i:s', time()),
                        ],
                        [
                            'id' => $lRights['id']
                        ]
                    ];
                } else {
                    $levelRightsInsert[] = [
                        'brand_id' => $brandId,
                        'uid' => $accountInfo['uid'],
                        'rights_source_id' => $cfg['rights_source_id'],
                        'rights_num' => $cfg['rights_data'],
                        'rights_status' => mBrandLevelRights::STATUS_NORMAL,
                        'addtime' => date('Y-m-d H:i:s', time()),
                        'edittime' => date('Y-m-d H:i:s', time()),
                    ];
                }
                $rightsName = $levelSourceRightsMap[$cfg['rights_source_id']]['rights_name'];
                //all
                $totalNum = $rightsNum = $cfg['rights_data'];
                if (isset($brandRightsAllMap[$cfg['rights_source_id']])) {
                    $rightsAll = $brandRightsAllMap[$cfg['rights_source_id']];
                    if ($rightsAll['rights_status'] != mBrandRightsAll::STATUS_NORMAL) {
                        $rightsAll['total_num'] = $rightsAll['rights_num'] = $lastRightsNum = 0;
                    }
                    if (mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM == $rightsType) {
                        $totalNum = $rightsAll['total_num'] + $cfg['rights_data'];
                        $rightsNum = $rightsAll['rights_num'] + $cfg['rights_data'];
                    } elseif (mBrandRightsSource::RIGHTS_TYPE_NUM == $rightsType) {
                        if ($totalNum == mBrandRightsSource::COUNT_UNLIMIT
                            || $rightsNum == mBrandRightsSource::COUNT_UNLIMIT
                            || $rightsAll['total_num'] == mBrandRightsSource::COUNT_UNLIMIT
                            || $rightsAll['rights_num'] == mBrandRightsSource::COUNT_UNLIMIT) {
                            $rightsNum = $totalNum = mBrandRightsSource::COUNT_UNLIMIT;
                        } else {
                            $totalNum = $rightsAll['total_num'] - $lastRightsNum + $cfg['rights_data'];
                            $rightsNum = $rightsAll['rights_num'] - $lastRightsNum + $cfg['rights_data'];
                        }

                    } else {
                        $totalNum = $rightsAll['total_num'];
                        $rightsNum = $rightsAll['rights_num'];
                    }

                    $rightsAllUpdate[] = [
                        [
                            'total_num' => $totalNum,
                            'rights_num' => $rightsNum,
                            'start_time' => $startTime,
                            'end_time' => $endTime,
                            'rights_status' => mBrandRightsAll::STATUS_NORMAL,
                        ],
                        [
                            'id' => $rightsAll['id'],
                        ]
                    ];
                    $recordInsert[] = [
                        'brand_id' => $brandId,
                        'rights_name' => $rightsName,
                        'rights_source_id' => $cfg['rights_source_id'],
                        'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL,
                        'source_id' => $lastLevel . '_' . $level,
                        'source_data' => json_encode([
                            'total_num' => $rightsAll['total_num'],
                            'rights_num' => $rightsAll['rights_num'],
                            'start_time' => $rightsAll['start_time'],
                            'end_time' => $rightsAll['end_time'],
                            'rights_status' => $rightsAll['rights_status'],
                        ]),
                        'operate_data' => json_encode([
                            'total_num' => $totalNum,
                            'rights_num' => $rightsNum,
                            'start_time' => $startTime,
                            'end_time' => $endTime,
                            'rights_status' => mBrandRightsAll::STATUS_NORMAL
                        ]),
                    ];
                } else {
                    $rightsAllInsert[] = [
                        'brand_id' => $brandId,
                        'rights_source_id' => $cfg['rights_source_id'],
                        'rights_name' => $rightsName,
                        'total_num' => $rightsNum,
                        'rights_num' => $rightsNum,
                        'start_time' => $startTime,
                        'end_time' => $endTime,
                        'rights_status' => mBrandRightsAll::STATUS_NORMAL,
                    ];

                    $recordInsert[] = [
                        'brand_id' => $brandId,
                        'rights_name' => $rightsName,
                        'rights_source_id' => $cfg['rights_source_id'],
                        'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL,
                        'source_id' => $lastLevel . '_' . $level,
                        'source_data' => json_encode([]),
                        'operate_data' => json_encode([
                            'total_num' => $rightsNum,
                            'rights_num' => $rightsNum,
                            'start_time' => $startTime,
                            'end_time' => $endTime,
                            'rights_status' => mBrandRightsAll::STATUS_NORMAL,
                        ]),
                    ];
                }

            }

            $result = mBrandLevelRights::action(function () use (
                $levelRightsLogInsert,
                $levelRightsLogUpdate,
                $levelRightsInsert,
                $levelRightsUpdate,
                $rightsAllUpdate,
                $rightsAllInsert,
                $recordInsert
            ) {
                if (!empty($levelRightsLogInsert)) {
                    $bResult = mBrandLevelRightsLog::dataMultiInsert($levelRightsLogInsert);
                    if (!$bResult) {
                        return false;
                    }
                }
                if (!empty($levelRightsLogUpdate)) {
                    $bResult = mBrandLevelRightsLog::dataMultiUpdate($levelRightsLogUpdate);
                    if (!$bResult) {
                        return false;
                    }
                }
                if (!empty($levelRightsInsert)) {
                    $bResult = mBrandLevelRights::dataMultiInsert($levelRightsInsert);
                    if (!$bResult) {
                        return false;
                    }
                }

                if (!empty($levelRightsUpdate)) {
                    $bResult = mBrandLevelRights::dataMultiUpdate($levelRightsUpdate);
                    if (!$bResult) {
                        return false;
                    }
                }

                if (!empty($rightsAllInsert)) {
                    $bResult = mBrandRightsAll::insert($rightsAllInsert);
                    if (!$bResult) {
                        return false;
                    }
                }

                if (!empty($rightsAllUpdate)) {
                    foreach ($rightsAllUpdate as $item) {
                        [$data, $where] = $item;
                        $bResult = mBrandRightsAll::update($data, $where);
                        if (!$bResult) {
                            return false;
                        }
                    }
                }

                if (!empty($recordInsert)) {
                    $bResult = mBrandRightsRecored::insert($recordInsert);
                    if (!$bResult) {
                        return false;
                    }
                }

                return true;
            });

            if (!$result) {
                Log::error('等级权益升级事务执行失败',
                    [
                        'mBrandLevelRights' => mBrandLevelRights::log(),
                        'mBrandLevelRightsLog' => mBrandLevelRightsLog::log(),
                        'mBrandRightsAll' => mBrandRightsAll::log(),
                        'mBrandRightsRecored' => mBrandRightsRecored::log(),
                    ]
                );
                throw new \Exception('事务执行失败');
            }

            //写入权益升级弹窗
            self::setLevelUpgradeAlert($brandId, $level);

            return true;
        } catch (\Exception $e) {
            Log::error('品牌等级升级后权益处理失败', ['error' => $e->getMessage(), 'args' => func_get_args()]);
            return false;
        }
    }

    /**
     * 等级降级处理
     * @param $brandId
     * @param $level
     * @return bool
     */
    public static function afterLevelDown($brandId, $level, $lastLevel)
    {
        try {
            if (!isset(self::BRAND_LEVELS[$level]) || !isset(self::BRAND_LEVELS[$lastLevel]) || $lastLevel - $level != 1) {
                throw new \Exception('等级参数错误!');
            }

            $brandInfo = mBrand::getInfo($brandId);

            if (mBrand::BRAND_TYPE_EXPIRE == $brandInfo['brand_type']) {
                $bRet = self::afterExpiredBrandLevelDown($brandId, $level, $lastLevel);
                if (!$bRet) {
                    throw new \Exception('过期品牌降级权益处理失败！');
                }
                return true;
            }

            //品牌账户信息
            $accountInfo = BrandAccountInfo::getOneByWhere([
                'type' => BrandAccountInfo::ACCOUNT_TYPE_BRAND,
                'brand_id' => $brandId,
                'account_status' => BrandAccountInfo::ACCOUNT_STATUS_USED
            ], ['id', 'in_start_time', 'in_end_time']);
            if (empty($accountInfo)) {
                throw new \Exception('品牌不存在或已过期!');
            }

            $startTime = strtotime($accountInfo['in_start_time']);
            $endTime = strtotime($accountInfo['in_end_time']);
            $endTime = strtotime(date('Y-m-d 23:59:59', $endTime));

            //全部等级权益信息
            $levelSourceRights = BrandLevelSourceRightsService::getLevelSourceRights();
            $levelSourceRightsMap = array_column($levelSourceRights, null, 'source_rights_id');
            //等级权益配置信息
            $levelRightsCfg = BrandLevelRightsConfigService::getLevelRightsConfig($level,
                mBrandLevelRightsConfig::STATUS_NORMAL);
            $levelRightsCfgMap = array_column($levelRightsCfg, null, 'rights_source_id');
            //删除上一级非消耗型权益日志
            $lastLevelRightsLogs = BrandLevelRightsLogService::getBrandOneLevelRights($brandId, $lastLevel);
            $lastLevelRightsLogsNums = array_column($lastLevelRightsLogs, 'rights_num', 'rights_source_id');
            $delLevelRightsLogData = [];
            foreach ($lastLevelRightsLogs as $log) {
                $sourceRights = $levelSourceRightsMap[$log['rights_source_id']];
                $rightsType = $sourceRights['rights_type'];
                if ($log['rights_status'] == BaseDbModel::STATUS_DELETE || $rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM) {
                    continue;
                }
                $delLevelRightsLogData[] = [
                    [
                        'rights_status' => BaseDbModel::STATUS_DELETE,
                        'edittime' => date('Y-m-d H:i:s', time())
                    ],
                    ['id' => $log['id']]
                ];
            }
            //更新等级权益
            $updateLevelRights = [];
            $updateRightsAll = [];
            $rightsRecordNew = [];
            $rightsMinLevels = BrandLevelRightsConfigService::getRightsMinLevel();
            $levelRights = self::brandLevelRights($brandId);
            $levelRightsIds = array_column($levelRights, 'rights_source_id');
            $brandAllRights = mBrandRightsAll::selectList([
                'brand_id' => $brandId,
                'rights_source_id' => $levelRightsIds
            ]);
            $brandAllRightsMap = array_column($brandAllRights, null, 'rights_source_id');
            //套餐权益
            $brandPackageRights = mBrandPackageRights::selectList([
                'brand_id' => $brandId,
                'rights_source_id' => $levelRightsIds,
                'rights_status' => mBrandPackageRights::STATUS_NORMAL,
                'start_time' => $startTime,
                'end_time' => $endTime,
            ]);
            $brandPackageRightsMap = array_column($brandPackageRights, null, 'rights_source_id');
            //运营添加的权益
            $rightsRecords = mBrandRightsRecored::selectList([
                'brand_id' => $brandId,
                'addtime[>=]' => $accountInfo['in_start_time'],
                'addtime[<=]' => $accountInfo['in_end_time'],
                'rights_source_id' => $levelRightsIds,
                'recored_type' => mBrandRightsRecored::RECORED_TYPE_ADMIN,
                'ORDER' => ['id' => 'DESC'],
            ]);
            $rightsRecordsMap = [];
            foreach ($rightsRecords as $record) {
                $rightsRecordsMap[$record['rights_source_id']][] = $record;
            }

            foreach ($levelRights as $rights) {
                $rightsType = $levelSourceRightsMap[$rights['rights_source_id']]['rights_type'];
                $rightsName = $levelSourceRightsMap[$rights['rights_source_id']]['rights_name'];
                //消耗型权益不变，数量型计算或取消，功能型按等级判断是否取消权益
                if (mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM == $rightsType) {
                    continue;
                }
                $allRightsInfo = $brandAllRightsMap[$rights['rights_source_id']];
                $hasLevelRights = $level >= $rightsMinLevels[$rights['rights_source_id']];

                $rightsNum = $levelRightsCfgMap[$rights['rights_source_id']]['rights_data'] ?? 0;

                if (!$hasLevelRights) {
                    //失去等级权益
                    $updateLevelRights[] = [
                        [
                            'rights_status' => mBrandLevelRights::STATUS_DELETE,
                            'edittime' => date('Y-m-d H:i:s', time()),
                            'rights_num' => 0,
                        ],
                        ['id' => $rights['id']]
                    ];
                    //套餐、运营添加都没有该权益则all失去权益
                    $rightsStatus = mBrandRightsAll::STATUS_DELETE;

                    $newRightsNum = $newTotalNum = 0;

                    if (isset($brandPackageRightsMap[$rights['rights_source_id']])) {
                        $rightsStatus = mBrandRightsAll::STATUS_NORMAL;
                        $newRightsNum = $brandPackageRightsMap[$rights['rights_source_id']]['rights_num'];
                        $newTotalNum = $brandPackageRightsMap[$rights['rights_source_id']]['rights_num'];
                    }

                    if (isset($rightsRecordsMap[$rights['rights_source_id']])) {
                        $opRecords = $rightsRecordsMap[$rights['rights_source_id']];
                        $opData = json_decode($opRecords[0]['operate_data'], true);
                        $lvRightsNum = $opData['op_level_rights_num'] ?? 0; //添加权益是的等级数量
                        $newRightsNum = isset($opData['rights_num']) ? $opData['rights_num'] - $lvRightsNum + $rightsNum : $newRightsNum;
                        $newRightsNum = $newRightsNum >= mBrandRightsSource::COUNT_UNLIMIT ? mBrandRightsSource::COUNT_UNLIMIT : $newRightsNum;
                        $newTotalNum = isset($opData['rights_num']) ? $opData['rights_num'] - $lvRightsNum + $rightsNum : $newTotalNum;
                        $newTotalNum = $newTotalNum >= mBrandRightsSource::COUNT_UNLIMIT ? mBrandRightsSource::COUNT_UNLIMIT : $newTotalNum;
                        $rightsStatus = mBrandRightsAll::STATUS_NORMAL;
                    }

                    $updateRightsAll[] = [
                        [
                            'rights_status' => $rightsStatus,
                            'rights_num' => $newRightsNum,
                            'total_num' => $newTotalNum,
                            'edittime' => date('Y-m-d', time()),
                        ],
                        [
                            'id' => $brandAllRightsMap[$rights['rights_source_id']]['id'],
                        ]
                    ];

                    $rightsRecordNew[] = [
                        'brand_id' => $brandId,
                        'rights_name' => $rightsName,
                        'rights_source_id' => $rights['rights_source_id'],
                        'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL_DEGRADE,
                        'source_id' => $lastLevel . '_' . $level,
                        'source_data' => json_encode([
                            'total_num' => $allRightsInfo['total_num'],
                            'rights_num' => $allRightsInfo['rights_num'],
                            'start_time' => $allRightsInfo['start_time'],
                            'end_time' => $allRightsInfo['end_time'],
                            'rights_status' => $allRightsInfo['rights_status'],
                        ]),
                        'operate_data' => json_encode([
                            'total_num' => $newTotalNum,
                            'rights_num' => $newRightsNum,
                            'start_time' => $allRightsInfo['start_time'],
                            'end_time' => $allRightsInfo['end_time'],
                            'rights_status' => $rightsStatus,
                        ]),
                    ];

                    continue;
                }

                //没有失去等级权益，数量型的权益更新数量
                if (mBrandRightsSource::RIGHTS_TYPE_NUM == $rightsType) {
                    $updateLevelRights[] = [
                        ['rights_num' => $rightsNum, 'edittime' => date('Y-m-d H:i:s', time())],
                        ['id' => $rights['id']]
                    ];
                    //更新all表数量型权益
                    $lastLevelRightsNum = $lastLevelRightsLogsNums[$rights['rights_source_id']] ?? 0;

                    if ($brandAllRightsMap[$rights['rights_source_id']]['rights_num'] == mBrandRightsSource::COUNT_UNLIMIT) {

                        $rawAllRightsNum = $rawAllRightsTotalNum = 0;

                        if (isset($brandPackageRightsMap[$rights['rights_source_id']])) {
                            $rawAllRightsNum = $brandPackageRightsMap[$rights['rights_source_id']]['rights_num'];
                            $rawAllRightsTotalNum = $brandPackageRightsMap[$rights['rights_source_id']]['rights_num'];
                        }

                        if (isset($rightsRecordsMap[$rights['rights_source_id']])) {
                            $opRecords = $rightsRecordsMap[$rights['rights_source_id']];
                            $opData = json_decode($opRecords[0]['operate_data'], true);
                            $lvRightsNum = $opData['op_level_rights_num'] ?? 0; //添加权益是的等级数量
                            $rawAllRightsNum = isset($opData['rights_num']) ? $opData['rights_num'] - $lvRightsNum : $rawAllRightsNum;
                            $rawAllRightsTotalNum = isset($opData['rights_num']) ? $opData['rights_num'] - $lvRightsNum : $rawAllRightsTotalNum;
                        }

                        $allRightsNum = $rawAllRightsNum + $rightsNum;

                        $allRightsTotalNum = $rawAllRightsTotalNum + $rightsNum;

                    } else {
                        $allRightsNum = $brandAllRightsMap[$rights['rights_source_id']]['rights_num'] - $lastLevelRightsNum + $rightsNum;

                        $allRightsTotalNum = $brandAllRightsMap[$rights['rights_source_id']]['total_num'] - $lastLevelRightsNum + $rightsNum;
                    }

                    $allRightsNum = $allRightsNum >= mBrandRightsSource::COUNT_UNLIMIT ? mBrandRightsSource::COUNT_UNLIMIT : $allRightsNum;

                    $allRightsTotalNum = $allRightsTotalNum >= mBrandRightsSource::COUNT_UNLIMIT ? mBrandRightsSource::COUNT_UNLIMIT : $allRightsTotalNum;

                    $updateRightsAll[] = [
                        [
                            'rights_num' => $allRightsNum,
                            'total_num' => $allRightsTotalNum,
                        ],
                        [
                            'id' => $brandAllRightsMap[$rights['rights_source_id']]['id'],
                            'rights_num' => $brandAllRightsMap[$rights['rights_source_id']]['rights_num'],
                            'total_num' => $brandAllRightsMap[$rights['rights_source_id']]['total_num'],
                        ]
                    ];

                    $rightsRecordNew[] = [
                        'brand_id' => $brandId,
                        'rights_name' => $rightsName,
                        'rights_source_id' => $rights['rights_source_id'],
                        'recored_type' => mBrandRightsRecored::RECORED_TYPE_LEVEL_DEGRADE,
                        'source_id' => $lastLevel . '_' . $level,
                        'source_data' => json_encode([
                            'total_num' => $allRightsInfo['total_num'],
                            'rights_num' => $allRightsInfo['rights_num'],
                            'start_time' => $allRightsInfo['start_time'],
                            'end_time' => $allRightsInfo['end_time'],
                            'rights_status' => $allRightsInfo['rights_status'],
                        ]),
                        'operate_data' => json_encode([
                            'total_num' => $allRightsTotalNum,
                            'rights_num' => $allRightsNum,
                            'start_time' => $allRightsInfo['start_time'],
                            'end_time' => $allRightsInfo['end_time'],
                            'rights_status' => $allRightsInfo['rights_status'],
                        ]),
                    ];
                }
            }

            $result = mBrandRightsAll::action(function () use (
                $delLevelRightsLogData,
                $updateLevelRights,
                $updateRightsAll,
                $rightsRecordNew
            ) {
                if (!empty($delLevelRightsLogData)) {
                    $bResult = mBrandLevelRightsLog::dataMultiUpdate($delLevelRightsLogData);
                    if (!$bResult) {
                        return false;
                    }
                }

                if (!empty($updateLevelRights)) {
                    $bResult = mBrandLevelRights::dataMultiUpdate($updateLevelRights);
                    if (!$bResult) {
                        return false;
                    }
                }

                if (!empty($updateRightsAll)) {
                    foreach ($updateRightsAll as $item) {
                        [$data, $where] = $item;
                        $bResult = mBrandRightsAll::update($data, $where);
                        if (!$bResult) {
                            return false;
                        }
                    }
                }

                if (!empty($rightsRecordNew)) {
                    $bResult = mBrandRightsRecored::insert($rightsRecordNew);
                    if (!$bResult) {
                        return false;
                    }
                }

                return true;
            });

            if (!$result) {
                Log::error('等级权益降级事务执行失败',
                    [
                        'mBrandLevelRights' => mBrandLevelRights::log(),
                        'mBrandLevelRightsLog' => mBrandLevelRightsLog::log(),
                        'mBrandRightsAll' => mBrandRightsAll::log(),
                        'mBrandRightsRecored' => mBrandRightsRecored::log(),
                    ]
                );
            }

            return $result ? true : false;
        } catch (\Exception $e) {
            Log::error('品牌等级降级后权益处理失败', ['error' => $e->getMessage(), 'args' => func_get_args()]);
            return false;
        }
    }

    public static function afterExpiredBrandLevelDown($brandId, $level, $lastLevel)
    {
        try {
            //全部等级权益信息
            $levelSourceRights = BrandLevelSourceRightsService::getLevelSourceRights();
            $levelSourceRightsMap = array_column($levelSourceRights, null, 'source_rights_id');
            //等级权益配置信息
            $levelRightsCfg = BrandLevelRightsConfigService::getLevelRightsConfig($level,
                mBrandLevelRightsConfig::STATUS_NORMAL);
            $levelRightsCfgMap = array_column($levelRightsCfg, null, 'rights_source_id');
            //删除上一级非消耗型权益日志
            $lastLevelRightsLogs = BrandLevelRightsLogService::getBrandOneLevelRights($brandId, $lastLevel);
            //权益获取最低等级
            $rightsMinLevels = BrandLevelRightsConfigService::getRightsMinLevel();

            $delLevelRightsLogData = [];
            $updateLevelRightsData = [];

            foreach ($lastLevelRightsLogs as $log) {
                $sourceRights = $levelSourceRightsMap[$log['rights_source_id']];
                $rightsType = $sourceRights['rights_type'];
                if ($log['rights_status'] == BaseDbModel::STATUS_DELETE || $rightsType == mBrandRightsSource::RIGHTS_TYPE_LIMIT_NUM) {
                    continue;
                }
                if ($level < $rightsMinLevels[$log['rights_source_id']]) {
                    //失去等级权益
                    $updateLevelRightsData[] = [
                        [
                            'rights_status' => mBrandLevelRights::STATUS_DELETE,
                            'rights_num' => 0,
                            'reserve_rights_num' => 0,
                            'edittime' => date('Y-m-d H:i:s', time())
                        ],
                        [
                            'brand_id' => $brandId,
                            'rights_source_id' => $log['rights_source_id']
                        ]
                    ];

                } elseif ($rightsType == mBrandRightsSource::RIGHTS_TYPE_NUM) {
                    //更新权益数量

                    $rightsNum = $levelRightsCfgMap[$log['rights_source_id']]['rights_data'];

                    $updateLevelRightsData[] = [
                        [
                            'rights_status' => mBrandLevelRights::STATUS_NORMAL,
                            'rights_num' => $rightsNum,
                            'reserve_rights_num' => $rightsNum,
                            'edittime' => date('Y-m-d H:i:s', time())
                        ],
                        [
                            'brand_id' => $brandId,
                            'rights_source_id' => $log['rights_source_id']
                        ]
                    ];
                }
                $delLevelRightsLogData[] = [
                    [
                        'rights_status' => BaseDbModel::STATUS_DELETE,
                        'edittime' => date('Y-m-d H:i:s', time())
                    ],
                    ['id' => $log['id']]
                ];
            }

            $result = mBrandLevelRights::action(function () use ($delLevelRightsLogData, $updateLevelRightsData) {
                if (!empty($delLevelRightsLogData)) {
                    $bRet = mBrandLevelRightsLog::dataMultiUpdate($delLevelRightsLogData);
                    if (!$bRet) {
                        return false;
                    }
                }
                if (!empty($updateLevelRightsData)) {
                    $bRet = mBrandLevelRights::dataMultiUpdate($updateLevelRightsData);
                    if (!$bRet) {
                        return false;
                    }
                }
                return true;
            });

            if (!$result) {
                throw new \Exception('过期品牌等级降级后权益事务处理失败');
            }

            return true;

        } catch (\Exception $e) {
            Log::error('过期品牌等级降级后权益处理失败', ['error' => $e->getMessage(), 'args' => func_get_args()]);
            return false;
        }
    }

}